package org.whatever.aha.zjut.platform.controller.competition;

import cn.dev33.satoken.annotation.SaCheckRole;
import cn.dev33.satoken.annotation.SaMode;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.swagger.annotations.*;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.whatever.aha.zjut.base.constant.AuthConst;
import org.whatever.aha.zjut.base.constant.ErrorCode;
import org.whatever.aha.zjut.base.constant.StatusConstant;
import org.whatever.aha.zjut.base.dto.AjaxResult;
import org.whatever.aha.zjut.base.exception.AppException;
import org.whatever.aha.zjut.platform.dto.competition.*;
import org.whatever.aha.zjut.platform.entity.competition.Competition;
import org.whatever.aha.zjut.platform.service.competition.CompetitionService;
import org.whatever.aha.zjut.platform.service.competition.CompetitionStageAwardService;
import org.whatever.aha.zjut.platform.vo.competition.CompeletedCompInfoVo;
import org.whatever.aha.zjut.platform.vo.competition.CompetitionDetailVo;
import org.whatever.aha.zjut.platform.vo.competition.CompetitionStageAwardVo;
import org.whatever.aha.zjut.platform.vo.competition.CompetitionStuRoughVo;

import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author Vc
 * @version 1.0
 * @Desc    TODO: 修改竞赛分页信息接口  返回值total分层      把total改成总数，不是页数
 * @date 2021/08/25 0:58
 */
@Api(tags = "赛事相关操作类")
@RequestMapping("/v1/competition")
@RequiredArgsConstructor
@RestController
@Validated
public class CompetitionController {
    final CompetitionService competitionService;
    final CompetitionStageAwardService competitionStageAwardService;

    /**
     * 分页获取竞赛粗略信息,默认时间排序
     *
     * @param compType  竞赛类型|1
     * @param compStatus  竞赛状态|1
     * @param compYear  竞赛年份|2021
     * @param pageNum   页数|1
     * @param pageSize  页大小|10
     * @return
     */
    @ApiOperation("分页获取所有竞赛粗略信息以及所有记录数")
    @GetMapping("/getRoughInfo")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "compType", value = "竞赛类型", dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "compStatus", value = "竞赛状态", dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "compYear", value = "竞赛年份", dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "pageNum", value = "页数", dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "pageSize", value = "页大小", dataTypeClass = Integer.class)
    })
    public AjaxResult<Map> getCompetitionRoughPageable(@RequestParam(value = "compType", required = false) Integer compType,
                                                              @RequestParam(value = "compStatus", required = false) Integer compStatus,
                                                              @RequestParam(value = "compYear", required = false) Integer compYear,
                                                              @RequestParam(value = "pageNum", required = true, defaultValue = "1") int pageNum,
                                                              @RequestParam(value = "pageSize", required = true, defaultValue = "10") int pageSize) {
        return AjaxResult.SUCCESS(competitionService.getCompetitionRoughPageable(compType, compStatus, compYear, (pageNum - 1) * pageSize, pageSize));
    }


    /**
     * 获取我参加的竞赛粗略信息
     *
     * @param compType  竞赛类型|1
     * @param compStatus  竞赛状态|1
     * @param compYear  竞赛年份|2021
     * @return
     */
    @ApiOperation("获取我的所有竞赛粗略信息")
    @GetMapping("/getStuRoughInfo")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "compType", value = "竞赛类型", dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "compStatus", value = "竞赛状态", dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "compYear", value = "竞赛年份", dataTypeClass = Integer.class)
    })
    public AjaxResult<List<CompetitionStuRoughVo>> getUserCompetitionRough(@RequestParam(value = "compType", required = false) Integer compType,
                                                                                   @RequestParam(value = "compStatus", required = false) Integer compStatus,
                                                                                   @RequestParam(value = "compYear", required = false) Integer compYear) {
        int userId = StpUtil.getLoginIdAsInt();
        return AjaxResult.SUCCESS(competitionService.getUserCompetitionRough(userId, compType, compStatus, compYear));
    }

    /**
     * 创建新的比赛全量信息
     *
     * @param competitionDetailDto  竞赛详细信息
     * @return
     */
    @SaCheckRole(value = {AuthConst.R_supper, AuthConst.R_school}, mode = SaMode.OR)
    @ApiOperation("创建新的比赛详细信息")
    @PostMapping("/createCompetition")
    public AjaxResult<Map> createCompetition(@ApiParam(value = "竞赛详细信息",required = true) @RequestBody @Validated CompetitionDetailDto competitionDetailDto) {
        //比赛届数必须更大
        int newTh = competitionService.getNewTh(competitionDetailDto.getCompetitionDto().getCompType()) - 1;
        if(competitionDetailDto.getCompetitionDto().getCompTh()< newTh){
            new AppException(ErrorCode.ILLEGAL_COMPETITION_TH);
        }
        //目前比赛流程最多支持初赛和复赛两个阶段
        if(competitionDetailDto.getCompetitionStageDetailDtoList().size() > 2){
            new AppException(ErrorCode.COMPETITION_STAGE_SUPPORT_MAX_TWO);
        }
        //正在进行中的比赛只能有一个
        Set<Object> types = competitionService.getOngoingCompType();
        if(types.contains(competitionDetailDto.getCompetitionDto().getCompType())){
            throw new AppException(ErrorCode.ONE_COMP_TYPE_IN_A_PERIOD);
        }
        //决赛提交时间段必须在初赛公示结束之后
        if(competitionDetailDto.getCompetitionStageDetailDtoList().size() > 1){
            int firstStageOrder = competitionDetailDto.getCompetitionStageDetailDtoList().get(0).getCompetitionStageDto().getStageOrder();
            // 如果初赛是getCompetitionStageDetailDtoList.get(1)
            if(firstStageOrder != StatusConstant.COMPETITION_STAGE_PRELIMINARY.getCode()){
                Date firstDate = competitionDetailDto.getCompetitionStageDetailDtoList().get(1).getCompetitionStageStatusDtoList()
                        .stream().filter(competitionStageStatusDto -> competitionStageStatusDto.getStatusOrder() == StatusConstant.COMPETITION_STAGE_STATUS_ORDER_PROMULGATE.getCode())
                        .map(CompetitionStageStatusDto::getStatusEndTime).collect(Collectors.toList()).get(0);
                Date secondDate = competitionDetailDto.getCompetitionStageDetailDtoList().get(0).getCompetitionStageStatusDtoList().stream()
                        .filter(competitionStageStatusDto -> competitionStageStatusDto.getStatusOrder() == StatusConstant.COMPETITION_STAGE_STATUS_ORDER_SUBMIT.getCode())
                        .map(CompetitionStageStatusDto::getStatusStartTime).collect(Collectors.toList()).get(0);
                if(firstDate.after(secondDate)){
                    throw new AppException(ErrorCode.STAGE_TIME);
                }
            }else {
                //初赛是getCompetitionStageDetailDtoList.get(0)
                Date firstDate = competitionDetailDto.getCompetitionStageDetailDtoList().get(0).getCompetitionStageStatusDtoList()
                        .stream().filter(competitionStageStatusDto -> competitionStageStatusDto.getStatusOrder() == StatusConstant.COMPETITION_STAGE_STATUS_ORDER_PROMULGATE.getCode())
                        .map(CompetitionStageStatusDto::getStatusEndTime).collect(Collectors.toList()).get(0);
                Date secondDate = competitionDetailDto.getCompetitionStageDetailDtoList().get(1).getCompetitionStageStatusDtoList().stream()
                        .filter(competitionStageStatusDto -> competitionStageStatusDto.getStatusOrder() == StatusConstant.COMPETITION_STAGE_STATUS_ORDER_SUBMIT.getCode())
                        .map(CompetitionStageStatusDto::getStatusStartTime).collect(Collectors.toList()).get(0);
                if(firstDate.after(secondDate)){
                    throw new AppException(ErrorCode.STAGE_TIME);
                }
            }
        }

        return AjaxResult.SUCCESS(competitionService.addCompDetail(competitionDetailDto));
    }

    /**
     * 当前比赛进入下一阶段
     *
     * @param compId    竞赛id
     * @return
     */
    @SaCheckRole(value = {AuthConst.R_supper, AuthConst.R_school}, mode = SaMode.OR)
    @ApiOperation("当前比赛进入下一个阶段")
    @PutMapping("/enterNext/{compId}")
    public AjaxResult<Integer> enterNextStatus(@PathVariable("compId") int compId){
        return AjaxResult.SUCCESS(competitionService.enterNextStatus(compId));
    }

    /**
     * 获取当前赛事最新届数
     *
     * @param compType    竞赛类型
     * @return
     */
    @ApiOperation("获取当前赛事最新届数")
    @GetMapping("/{compType}")
    public AjaxResult<Integer> getNewTh(@PathVariable("compType") int compType){
        return AjaxResult.SUCCESS(competitionService.getNewTh(compType));
    }

    /**
     * 获取当前未完结的竞赛信息
     *
     * @return
     */
    @ApiOperation("获取当前正在进行的竞赛id列表")
    @GetMapping("/getOngoingComp")
    public AjaxResult<List<Map<String , Object>>> getOngoingComp(){
        return AjaxResult.SUCCESS(competitionService.getOngoingComp());
    }


    /**
     * 根据全量比赛信息修改比赛信息
     *
     * @param competitionDetailVo
     * @return
     */
    @SaCheckRole(value = {AuthConst.R_supper, AuthConst.R_school}, mode = SaMode.OR)
    @ApiOperation("根据全量比赛信息修改比赛信息")
    @PutMapping("/updateCompetition")
    public AjaxResult<Object> updateCompetition( @ApiParam(value = "竞赛详细信息",required = true) @RequestBody @Validated CompetitionDetailVo competitionDetailVo) {
        int compId = competitionDetailVo.getCompetitionVo().getCompId();
        Competition competition = competitionService.getCompetitionById(compId);
        //不存在此比赛
        if(competition == null){
            throw new AppException(ErrorCode.COMPETITION_NOT_EXISTS);
        }
        //不可以修改已完结比赛
        if(competition.getCompStatus().equals(StatusConstant.COMPETITION_STATUS_COMPELETED.getCode())){
            throw new AppException(ErrorCode.ILLEGAL_UPDATE_COMPELETED_COMPETITION);
        }


        int compType = competitionDetailVo.getCompetitionVo().getCompType();

        int newTh = competitionService.getNewThExceptThis(compType,compId);
        return competitionDetailVo.getCompetitionVo().getCompTh() < newTh ? AjaxResult.FAIL("比赛届数只可以大于已存在最大届数！",null): AjaxResult.SUCCESS(competitionService.updateCompById(competitionDetailVo));
    }

    /**
     * 根据比赛Id删除比赛
     *
     * @param compId
     * @return
     */
    @SaCheckRole(value = {AuthConst.R_supper, AuthConst.R_school}, mode = SaMode.OR)
    @ApiOperation("根据比赛Id删除比赛")
    @DeleteMapping("/{compId}")
    public AjaxResult<Object> deleteCompetitionById(@PathVariable("compId") int compId) {
        return AjaxResult.SUCCESS(competitionService.deleteComp(compId));
    }

    /**
     * 根据比赛Id获取比赛全量信息
     *
     * @param compId
     * @return
     */
    @ApiOperation("根据比赛Id获取比赛全量信息")
    @GetMapping("/getCompetitionInfo/{compId}")
    public AjaxResult<CompetitionDetailVo> getCompetitionInfo(@PathVariable("compId")int compId){
        return AjaxResult.SUCCESS(competitionService.getCompetitionInfo(compId));
    }

    /**
     * 获取当前最新赛事的状态
     *
     * @return
     */
    @ApiOperation("获取当前最新赛事的状态")
    @GetMapping("/getCompStatusInfo")
    public AjaxResult<List<Map<String , Object>>> getCompStatusInfo(){
        return AjaxResult.SUCCESS(competitionService.getCompStatusInfo());
    }

    /**
     * 创建项目时需要获取的竞赛相关信息
     *
     * @param compId
     * @return
     */
    @ApiOperation("创建项目时需要获取的竞赛相关信息")
    @GetMapping("/getCompInfoWhenCreateProject/{compId}")
    public AjaxResult<Map<String , Object>> getCompInfoWhenCreateProject(@PathVariable("compId") int compId){
        return AjaxResult.SUCCESS(competitionService.getCompInfoWhenCreateProject(compId));
    }

    /**
     * 根据比赛类型获取已结束的比赛年份和对应的阶段ID、阶段名
     *
     * @param compType
     * @return
     */
    @ApiOperation("根据比赛类型获取已结束的比赛年份和对应的阶段ID、阶段名")
    @GetMapping("/getCompeletedCompInfo/{compType}")
    public AjaxResult<List<CompeletedCompInfoVo>> getCompeletedCompInfo(@PathVariable("compType") int compType){
        return AjaxResult.SUCCESS(competitionService.getCompeletedCompInfo(compType));
    }

    /**
     * 根据竞赛stageId获取此阶段奖项设置信息
     *
     * @param stageId
     * @return
     */
    @SaCheckRole(value = {AuthConst.R_supper, AuthConst.R_school}, mode = SaMode.OR)
    @GetMapping("/getStageAwardInfo/{stageId}")
    public AjaxResult<List<CompetitionStageAwardVo>> getStageAwardInfo(@PathVariable("stageId") int stageId){
        return AjaxResult.SUCCESS(competitionStageAwardService.getCompStageAwardListById(stageId));
    }
}
